package com.practice.retry;

import org.apache.log4j.Logger;

/**
 * This abstract class provides retry mechanism for a method that returns a integer as result.
 * And calling start method causes the task to be executed and retry when failed. 
 * @author Leonardo
 *
 */
public class IntegerWithoutExceptionRetryWorker extends RetryWorker {

	private static final Logger logger = Logger.getLogger(IntegerWithoutExceptionRetryWorker.class.getSimpleName());
	
	private int successValue = 0;

	/**
	 * 
	 * @param task
	 * @param taskDescription - Log content will contain this description.
	 * @return If task failed at last, return FAILED (-1).
	 * Otherwise return retried times. (If task succeed at first time, return 0.)
	 */
	public void start(IntegerWithoutExceptionRetryTask task, String taskDescription) {
		if (taskLogger == null) {
			taskLogger = logger;
		}
		
		if (task == null) {
			taskLogger.error("No task");
			return;
		}
		
		String failedLogFormat;
		if (taskDescription != null && !"".equals(taskDescription)) {
			failedLogFormat = "Failed: " + taskDescription + " (Retrun value: %d. Retried: %d.)";
		} else {
			failedLogFormat = "Failed. (Retrun value: %d. Retried times: %d.)";
		}
		
		int returnValue;
		for (int retryCount = 0; retryCount <= maxRetryCount; retryCount++) {
			task.setRetriedTimes(retryCount);
			
			returnValue = task.run();			
			if(successValue == returnValue) {
				task.setSuccess(true);
				break;
			} else {
				logger.error(String.format(failedLogFormat, returnValue, retryCount));
				
				if (retryCount < maxRetryCount) {
					try {
						Thread.sleep(sleepMilliseconds);
					} catch (InterruptedException interruptedEx){
						logger.error("Sleep before retry failed.", interruptedEx);
					}
				} else {
					task.setSuccess(false);
				}
			}
		}
	}
	
	/**
	 * Gets success value of task.
	 */
	public int getSuccessValue() {
		return successValue;
	}

	/**
	 * Sets success value of task. 
	 * If return value of task equals this value, task is successful.
	 * Default success value is 0.
	 */
	public void setSuccessValue(int successValue) {
		this.successValue = successValue;
	}
}
